/**
 * Abstrakcyjna klasa widoku wskaźnika. Obserwuje zmiany w modelu i je maluje.
 */

package com.beans.indicator.view;

import com.beans.indicator.constans.IndicatorConstans;
import com.beans.indicator.model.IndicatorModel;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.image.BufferedImage;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JComponent;

/**
 *
 * @author Wojtek
 */
public abstract class AbstractIndicatorView extends JComponent implements Observer {
    protected boolean diodeVisible;
    protected Color background = Color.ORANGE;
    protected int tickCount = 60;
    protected int largeTickInterval = 5;
    protected String title = "title";
    protected String unit;
    Color colo1 = new Color(255,0,51);
    Color color = new Color(153,0,51);

    //zmienne określające co trzeba namalować
    private boolean repaintIndicator = true, repaintCritical = true, repaintFace = true,
            repaintTitle = true;

    protected BufferedImage indicatorImage, faceImage, criticalImage, diodeImage, titleImage;

    protected IndicatorModel model;

    public AbstractIndicatorView(IndicatorModel model) {
        this.model = model;
        model.addObserver(this);

        //dodajemy listener na zmianę rozmiaru komponentu
        this.addComponentListener(new ComponentListener() {

            public void componentResized(ComponentEvent e) {
                repaintIndicator = repaintCritical = repaintFace = true;
                repaint();
            }

            public void componentMoved(ComponentEvent e) {
            }

            public void componentShown(ComponentEvent e) {
            }

            public void componentHidden(ComponentEvent e) {
            }
        });
    }

    @Override
    public void setBackground(Color background) {
        this.background = background;
        repaintFace = true;
    }

    @Override
    public Color getBackground() {
        return background;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
        repaintTitle = true;
    }

    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
        repaintFace = true;
    }

    public boolean isDiodeVisible() {
        return diodeVisible;
    }

    public void setDiodeVisible(boolean diodeVisible) {
        this.diodeVisible = diodeVisible;
        repaintFace = true;
    }

    public void setTickCount(int tickCount) {
        this.tickCount = tickCount;
        repaintFace = true;
    }

    public int getTickCount() {
        return tickCount;
    }

     public int getLargeTickInterval() {
        return largeTickInterval;
    }

    public void setLargeTickInterval(int largeTickInterval) {
        this.largeTickInterval = largeTickInterval;
        repaintFace = true;
    }

    @Override
    public void update(Observable o, Object arg) {
        if (arg instanceof IndicatorConstans) {
            IndicatorConstans ic = (IndicatorConstans)arg;
            switch (ic) {
                case VALUE_CHANGED:
                    repaintIndicator = true;
                    break;
                case RANGE_CHANGED:
                    repaintFace = true;
                    break;
                case CRITICAL_CHANGED:
                    repaintCritical = true;
                    break;
            }
        }

        repaint();
    }

    @Override
    protected void paintComponent(Graphics g) {
        if (repaintFace) {
            faceImage = (BufferedImage)createImage(getHeight(), getWidth());
            paintIndicatorFace(faceImage.getGraphics());
            repaintFace = false;
        }
        if (repaintIndicator) {
            //BufferedImage.TYPE_INT_ARGB zapewnia przezroczystosc
            indicatorImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
            paintIndicator(indicatorImage.getGraphics());
        }
        if(repaintTitle){
            titleImage = new BufferedImage(getWidth(),getHeight(),BufferedImage.TYPE_INT_ARGB);
            paintTitle(titleImage.getGraphics(), title);
        }
        diodeImage = null;
        if(diodeVisible){
            diodeImage = new BufferedImage(getWidth(),getHeight(),BufferedImage.TYPE_INT_ARGB);
            if(model.getValue() >= model.getMinCriticalValue())
                if(model.getValue() <= model.getMaxCriticalValue())
            paintDiode(diodeImage.getGraphics(),colo1);
                else paintDiode(diodeImage.getGraphics(),color);
            else
                paintDiode(diodeImage.getGraphics(),color);
        }
        g.drawImage(faceImage, 0, 0, null);
        g.drawImage(indicatorImage, 0, 0, null);
        g.drawImage(diodeImage, 0, 0, null);
        g.drawImage(titleImage,0,0,null);
    }

    protected Graphics2D getAAInstance(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
        return g2;
    }

    protected abstract void paintIndicatorFace(Graphics g);
    protected abstract void paintIndicator(Graphics g);
    protected abstract void paintDiode(Graphics g,Color c);
    protected abstract void paintTitle(Graphics g,String label);
}
